﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using MathExpression;

namespace SimplexSolver
{
    public class Restriction
    {
        public ReadOnlyCollection<IMathExpression> DataRow
        {
            get { return _dataRow.ToList().AsReadOnly(); }
        }

        private readonly IMathExpression[] _dataRow;

        public EIneqMode IneqMode { get; private set; }

        public IMathExpression Limit { get; private set; }

        private Restriction(IEnumerable<IMathExpression> dataRow, EIneqMode ineqMode, double limit)
        {
            _dataRow = dataRow.ToArray();
            IneqMode = ineqMode;
            Limit = ExpressionFactory.Create(limit);
        }

        public Restriction(IEnumerable<IMathExpression> dataRow, EIneqMode ineqMode, IMathExpression limit)
        {
            _dataRow = dataRow.ToArray();
            IneqMode = ineqMode;
            Limit = limit.Clone();
        }

        public override bool Equals(object obj)
        {
            if (!(obj is Restriction))
            {
                return false;
            }
            if (this == obj)
            {
                return true;
            }
            var restriction = (Restriction) obj;
            ReadOnlyCollection<IMathExpression> dataRow = restriction.DataRow;
            for (int i = 0; i < _dataRow.Length; i++)
            {
                if (!_dataRow[i].Equals(dataRow[i]))
                    return false;
            }
            if (restriction.IneqMode != IneqMode)
            {
                return false;
            }
            return restriction.Limit.Equals(Limit);
        }

        public bool Equals(Restriction other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return Equals(other._dataRow, _dataRow) && Equals(other.IneqMode, IneqMode) && Equals(other.Limit, Limit);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                int result = (_dataRow != null ? _dataRow.GetHashCode() : 0);
                result = (result*397) ^ IneqMode.GetHashCode();
                result = (result*397) ^ (Limit != null ? Limit.GetHashCode() : 0);
                return result;
            }
        }

        public enum EIneqMode
        {
            LessOrEqual,
            Equal,
            MoreOrEqual
        }
    }
}